<?php
namespace daicuo;

class Term
{
    /**
     * 架构函数
     * @param array $config
    public function __construct($config)
    {
        //self::$config = array_merge(self::$config, $config);
    }
    */
    
    // 错误信息
    protected static $error = 'error';
    
    /**
     * 获取错误信息
     * @return mixed
     */
    public static function getError()
    {
        return self::$error;
    }

    /**
     * 批量增加队列
     * @param array $list 写入数据（二维数组） 
     * @return mixed $mixed 添加成功返回自增ID数据集
     */
    public static function save_all($list=[])
    {
        //关联新增只有循环操作
        foreach($list as $key=>$data){
            $status[$key] = self::save($data);
        }
        //缓存标识清理
        DcCacheTag('common/Term/Item', 'clear');
        //返回结果
        return $status;
    }
    
    /**
     * 按termId删除一个队列
     * @param int $termId ID值
     * @return bool $bool true|false
     */
    public static function delete_id($termId='')
    {
        $value = trim($termId);
        if($termId < 1){
            return '0';
        }
        if( self::childrens($termId) ){
            return '0';
        }
        $where = array();
        $where['term_id'] = ['eq', $termId];
        if( self::delete($where,'term_much,term_meta') ){
            return true;
        }
        return false;
    }
    
    /**
     * 按termId删除一个队列
     * @param mixed $ids 必需;ID值,多个用逗号分隔;默认：空
     * @return array $arrsy 多条删除记录
     */
    public static function delete_ids($ids='')
    {
        $result = [];
        if( is_string($ids) ){
            $ids = explode(',',$ids);
        }
        foreach($ids as $key=>$value){
            array_push($result, self::delete_id($value));
        }
        return $result;
    }
    
    /**
     * 按模块名删除整个模块的分类
     * @param string $module 模块名
     * @return array $array 影响条数
     */
    public static function delete_module($module='')
    {
        if($module){
           return self::delete_all(['term_module'=>['eq',$module]]); 
        }
        return ['term'=>0,'term_much'=>0,'term_meta'=>0,'term_map'=>0];
    }
    
    /**
     * 批量删除分类数据
     * @param array $where 查询条件
     * @return array $array 影响条数
     */
    public static function delete_all($where=[])
    {
        $status = ['term'=>0,'term_much'=>0,'term_meta'=>0,'term_map'=>0];
        $term_id = db('term')->where($where)->column('term_id');
        if($term_id){
            $term_much_id = db('termMuch')->where(['term_id'=>['in',$term_id]])->column('term_much_id');
            //定义钩子参数
            $hookParams = ['term_id'=>$term_id, 'term_much_id'=>$term_much_id];
            //预留钩子term_delete_all_before
            \think\Hook::listen('term_delete_all_before', $hookParams);
            if($term_much_id){
                $status['term_map'] = db('termMap')->where(['term_much_id'=>['in',$term_much_id]])->delete();
            }
            $status['term_meta'] = db('termMeta')->where(['term_id'=>['in',$term_id]])->delete();
            $status['term_much'] = db('termMuch')->where(['term_id'=>['in',$term_id]])->delete();
            $status['term'] = db('term')->where(['term_id'=>['in',$term_id]])->delete();
            //缓存标识清理
            DcCacheTag('common/Term/Item', 'clear');
            //预留钩子term_delete_all_after
            \think\Hook::listen('term_delete_all_after', $hookParams, $status);
        }
        return $status;
    }
    
    /**
     * 按termId修改一个队列
     * @param string $value 字段值
     * @param array $data 写入数据（一维数组） 
     * @return mixed $mixed obj|null
     */
    public static function update_id($id, $data)
    {
        if($id < 1){
            return null;
        }
        $where = array();
        $where['term_id'] = ['eq', $id];
        return self::update($where, $data, 'term_much,term_meta');
    }
    
    /**
     * 通过termId获取队列信息
     * @param string $value 字段值 
     * @param bool $cache 是否开启缓存功能 由后台统一配置
     * @return mixed $mixed array|null
     */
    public static function get_id($value, $cache=true)
    {
        if ( !$value ) {
            return null;
        }
        $data = self::get([
            'cache' => $cache,
            'field' => '*',
            'where' => ['term_id'=>['eq', $value]],
            'with'  => 'term_much,term_meta',
            'view'  => [],
        ]);
        return self::meta_attr($data);
    }
    
    /**
     * 创建一个新队列
     * @param array $data 写入数据（一维数组） 
     * @param string|array $relation 关联表 
     * @return mixed $mixed null|obj
     */
    public static function save($data, $relation='term_much,term_meta')
    {
        //数据验证及格式化数据
        if(!$data = self::data_post($data)){
            return null;
		}
        //钩子传参定义
        $params = array();
        $params['data'] = $data;
        $params['relation'] = $relation;
        $params['result'] = false;
        unset($data);unset($relation);
        //预埋钩子
        \think\Hook::listen('term_save_before', $params);
        //添加数据
        if( false == $params['result'] ){
            $params['result'] = DcDbSave('common/Term', $params['data'], $params['relation']);
        }
        //预埋钩子
        \think\Hook::listen('term_save_after', $params);
        //返回结果
        return $params['result'];
    }
    
    /**
     * 按条件关联删除一个队列
     * @param array $where 必需;删除条件;默认：空
     * @param mixed $relation 可选;关联表string|array;默认：term_much,term_meta
     * @return mixed $mixed null|obj
     */
    public static function delete($where=[], $relation='term_much,term_meta')
    {
        //钩子传参定义
        $params = array();
        $params['where'] = $where;
        $params['relation'] = $relation;
        $params['result'] = 0;
        unset($where);unset($data);unset($relation);
        //预埋钩子
        \think\Hook::listen('term_delete_before', $params);
        //删除数据
        if( 0 == $params['result'] ){
            $params['result'] = DcDbDelete('common/Term', $params['where'], $params['relation']);
            //删除关系表
            if($params['result']->term_much_id){
                $resultMap = db('termMap')->where(['term_much_id'=>['eq',$params['result']->term_much_id]])->delete();
                $params['result']->RESULT = array_merge($params['result']->RESULT, [$resultMap]);
            }
        }
        //预埋钩子
        \think\Hook::listen('term_delete_after', $params);
        //返回结果
        return $params['result'];
    }
    
    /**
     * 修改一个队列
     * @param array $where 修改条件
     * @param array $data 写入数据（一维数组） 
     * @param string|array $relation 关联表
     * @return null|obj 成功时返回obj
     */
    public static function update($where, $data, $relation='term_much,term_meta')
    {
        //类型不可修改去掉此字段
        unset($data['term_much_type']);
        //数据验证及格式化数据
        if(!$data = self::data_post($data)){
            return null;
		}
        //钩子传参定义
        $params = array();
        $params['where'] = $where;
        $params['data'] = $data;
        $params['relation'] = $relation;
        unset($where);unset($data);unset($relation);
        //预埋钩子
        \think\Hook::listen('term_update_before', $params);
        //修改数据
        if( false == $params['result'] ){
            $params['result'] = DcDbUpdate('common/Term', $params['where'], $params['data'], $params['relation']);
        }
        //预埋钩子
        \think\Hook::listen('term_update_after', $params);
        //返回结果
        return $params['result'];
    }
    
    /**
     * 按条件查询一个队列
     * @param array $where 查询条件（一维数组）
     * @return obj|null 成功时返回obj
     */
    public static function get($args)
    {
        //格式验证
        if(!is_array($args)){
            return null;
        }
        //钩子传参定义
        $params = array();
        $params['result'] = false;
        $params['args'] = DcArrayArgs($args, [
            'cache'     => true,
            'field'     => '',//term.*,termMuch.term_much_id as ids
            'fetchSql'  => false,
            'where'     => '',
            'with'      => 'term_meta',//['termMuch','termMeta'],term_much,term_meta
            'view'      => [
                ['term','term_id,term_name,term_slug,term_module,term_status,term_order'],
                ['term_much', 'term_much_id,term_much_type,term_much_info,term_much_parent,term_much_count', 'term_much.term_id=term.term_id'],
                ['term_meta', 'term_meta_id', 'term_meta.term_id=term.term_id']
            ],
        ]);unset($args);//旧参数
        //预埋钩子
        \think\Hook::listen('term_get_before', $params);
        //查询数据
        if( false == $params['result'] ){
            $params['result'] = DcDbFind('common/Term', $params['args']);
        }
        //预埋钩子
        \think\Hook::listen('term_get_after', $params);
        //返回结果
        return $params['result'];
    }
    
    /**
     * 按条件查询多个队列
     * @param array $args 查询条件（一维数组）
     * @return obj|null 成功时返回obj
     */
    public static function all($args)
    {
        //格式验证
        if(!is_array($args)){
            return null;
        }
        //钩子传参定义
        $params = array();
        $params['result'] = false;
        $params['args'] = DcArrayArgs($args, [
            'cache'     => true,
            'field'     => '',
            'fetchSql'  => false,
            'sort'      => 'term_id',
            'order'     => 'desc',
            'paginate'  => '',
            'where'     => '',
            'with'      => [],
            'view'      => [
                ['term', 'term_id,term_name,term_slug,term_module,term_status,term_order'],
                ['term_much', 'term_much_id,term_much_type,term_much_info,term_much_parent,term_much_count', 'term_much.term_id=term.term_id'],
                //['term_meta', 'term_meta_id', 'term_meta.term_id=term.term_id']
            ],
        ]);unset($args);//旧参数
        //查询分类数据前的钩子
        \think\Hook::listen('term_all_before', $params);
        //数据库查询
        if( false == $params['result'] ){
            $params['result'] = DcDbSelect('common/Term', $params['args']);
        }
        //查询数据后的钩子
        \think\Hook::listen('term_all_after', $params);
        //返回结果
        return $params['result'];
    }
    
    /**
     * 按条件一次性获取所有队列/后续做无限递归处理
     * @param array $args 查询条件（一维数组）
     * @return mixed $mixed null|array
     */
    public static function all_pad($args=[])
    {
        //格式验证
        if(!is_array($args)){
            return null;
        }
        //合并参数
        $args = DcArrayArgs($args, [
            //'limit'   => 100,
            'cache'     => true,
            'status'    => 'normal',
            'tree'      => false,
            'level'     => false,
            'type'      => 'category',
            'sort'      => 'term_id',
            'order'     => 'desc',
        ]);
        //固定参数
        $args['paginate'] = false;
        $args['where']['term_status'] = ['eq', $args['status']];
        $args['where']['term_much_type'] = ['eq', $args['type']];
        //动态参数
        if($args['searchText']){
            $args['where']['term_name|term_slug'] = ['like','%'.$args['searchText'].'%'];
        }else{
            if($args['ids']){
                $args['where']['term_id'] = ['in', $args['ids']];
            }
            if($args['name']){
                $args['where']['term_name'] = ['like','%'.$args['name'].'%'];
            }
            if($args['slug']){
                $args['where']['term_slug'] = ['like','%'.$args['slug'].'%'];
            }
            if($args['module']){
                $args['where']['term_module'] = ['eq', $args['module']];
            }
        }
        unset($args['type']);
        unset($args['ids']);
        unset($args['name']);
        unset($args['slug']);
        unset($args['module']);
        unset($args['searchText']);
        //调用数据
        $list = DcArrayResult(self::all($args));
        //是否为空
        if(is_null($list)){
            return null;
        }
        //是否转换成树形
        if($args['tree']){
            $list = list_to_tree($list, 'term_much_id', 'term_much_parent');
        }
        //树形是否还原为层极
        if($args['level']){
            $list = tree_to_level($list, 'term_name');
        }
        //返回结果
        return $list;
    }
    
    /**
     * 获取递归层级处理后的队列列表
     * @param array $args 查询条件（参数请参考手册）
     * @return mixed null|array
     */
    public static function tree($args=[])
    {
        $args = DcArrayArgs($args,[
            'tree'       => true,
            'level'      => true,
            'type'       => 'category',
            'sort'       => 'term_id',
            'order'      => 'desc',
        ]);
        $terms = self::all_pad($args);
        //是否分页显示处理后的数据
        if( $terms && $args['paginate'] ){
            return self::tree_to_page($terms, $args['paginate']);
        }
        return $terms;
    }
    
    /**
     * 按分页格式返回递归处理后的数据
     * @param array $terms 递归处理后的数据列表
     * @param array $paginate 分页参数
     * @return array 符合TP分页数据格式的数据
     */
    public static function tree_to_page($terms=[], $paginate=[])
    {
        $page = array();
        $page['total'] = count($terms);
        $page['per_page'] = DcEmpty($paginate['list_rows'], 10);
        $page['current_page'] = DcEmpty($paginate['page'], 1);
        $page['last_page'] = ceil($page['total']/$page['per_page']);
        //计算偏移量
        $offset = ($page['current_page']-1)*$page['per_page'];
        if ( $offset >= count( $terms ) ) {
            $page['data'] = array();
        } else {
            $page['data'] = array_slice( $terms, $offset, $page['per_page'], false );
        }
        unset($terms);
        return $page;
    }
    
    /**
     * 快速生成select标签Option属性的对应关系 id=>name
     * @param array $args 查询条件（一维数组）
     * @return mixed null|array;
     */
    public static function option($args=[])
    {
        $args = DcArrayArgs($args,[
            'cache'      => false,
            'tree'       => true,
            'level'      => true,
            'type'       => 'category',
            'sort'       => 'term_order desc,term_id',
            'order'      => 'desc',
            'isSelect'   => false,
            'fieldKey'   => 'term_id',
            'fieldValue' => 'term_name',
        ]);
        //拼装数据
        $array = array();
        if($args['isSelect']){
            $array[0] = ' ';
        }
        foreach(self::all_pad($args) as $key=>$value){
            $array[$value[$args['fieldKey']]] = $value[$args['fieldValue']];
        }
        return $array;
    }
    
    /**
     * 快速生成字段与其它字段对应关系
     * @param string $field_key 用做KEY的字段
     * @param string $field_value 用做value的字段
     * @param string $type 分类法规则
     * @param bool $tree 是否树形
     * @param bool $level 是否将树形还原成层级
     * @return mixed null|array;
     */
    public static function fields($field_key='term_id', $field_value='term_slug', $type='category', $tree=false, $level=false)
    {
        return self::option([
            'cache' => false,
            'sort'  => 'term_order',
            'order' => 'desc',
            'tree'  => $tree,
            'level' => $level,
            'type'  => $type,
        ]);
    }
    
    /**
     * 通过队列ID获取该队列的所有子集
     * @param int $term_id 队列ID
     * @param string $term_type 分类法规则
     * @return mixed array|null
     */
    public static function childrens($term_id='', $term_type='category')
    {
        if( $terms = self::all_pad(['cache'=>true,'type'=>$term_type]) ){
            return get_childs($terms, $term_id);
        }
        return null;
    }
    
    /**
     * 通过队列的父ID获取该队列的所有父级
     * @param int $term_pid 分类父ID
     * @param string $term_type 分类法规则
     * @return mixed array|null
     */
    public static function parents($term_pid='', $term_type='category')
    {
        if( $terms = self::all_pad(['cache'=>true,'type'=>$term_type]) ){
            return get_parents($terms, $term_pid);
        }
        return null;
    }
    
    /**
     * 获取队列层级ID对应关系
     * @param string $term_type 分类法规则
     * @return mixed null|array
     */
    public static function hierarchy($term_type='category')
    {
        $terms = self::all_pad(['cache'=>true,'type'=>$term_type]);
        $children = array();
        foreach ( $terms as $key => $value ) {
            if ( $value['term_much_parent'] > 0 ) {
                $children[ $value['term_much_parent'] ][] = $value['term_id'];
            }
        }
        return $children;
    }
    
    /**
     * 修改器、转换post数据
     * @param array $data 表单数据
     * @return array 关联写入数据格式
     */
    public static function data_post($data)
    {
        // 表单验证
        $validate = [];
        $validate['data'] = $data;
        $validate['error'] = '';
        $validate['result'] = true;
        // 定义钩子参数
        \think\Hook::listen('form_validate', $validate);
        if($validate['result'] == false){
            self::$error = $validate['error'];
            return null;
        }
        unset($validate);
        // 数据整理成关联写入的格式
        //$data = DcDataToOne($data, 'term_much_type,term_much_info,term_much_parent,term_much_count,term_id', 'term_much');
        //$data = DcDataToMany($data, 'term_tpl,term_test', 'term_meta');
        $data = DcDataToOne($data, DcConfig('custom_fields.term_much'), 'term_much');
        $data = DcDataToMany($data, DcConfig('custom_fields.term_meta'), 'term_meta');
        return $data;
    }
    
    /**
     * 获取器、格式化扩展表数据
     * @param mixed $data 一维数组或OBJ数据集(array|obj)
     * @return mixed $mixed 格式化后的数据(array|null)
     */
    public static function meta_attr($data)
    {
        if( is_null($data) ){
            return null;
        }
        if( is_object($data) ){
            $data = $data->toArray();
        }
        $data = array_merge($data, DcManyToData($data, 'term_meta'));
        
        unset($data['term_meta']);
        
        return $data;
    }
    
}